package org.dba;


import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.StringTokenizer;
import java.util.Vector;

public class ServerLoader {
	
	private static final Class parameters[];
	static {
		parameters = (new Class[] { java.net.URL.class });
	}

	public ServerLoader() {
	}

	public boolean pluginLoad(String pluginDir) throws IOException {
		/**
		 * estimate the lib directory
		 */
		File pluginLibDir = new File(pluginDir, "lib");
		if (!pluginLibDir.exists())
			return false;
		if (!pluginLibDir.isDirectory())
			return false;
		File pluginJars[] = getFilesInDirectory(pluginLibDir, "jar", null);
		for (int i = 0; i < pluginJars.length; i++)
			addFile(pluginJars[i]);
		/**
		 * estimate the config directory
		 */
		File configDir = new File(pluginDir, "config");
		if (!configDir.exists())
			return false;
		if (!configDir.isDirectory())
			return false;
		File pluginXml[] = getFilesInDirectory(configDir, "xml", null);
		for (int i = 0; i < pluginXml.length; i++)
			addFile(pluginXml[i]);
		File folderInDirectory[] = getFolderInDirectory(pluginLibDir);
		for (int f = 0; f < folderInDirectory.length; f++) {
			pluginJars = getFilesInDirectory(folderInDirectory[f], "jar", null);
			pluginXml = getFilesInDirectory(pluginLibDir, "xml", null);
			for (int i = 0; i < pluginXml.length; i++)
				addFile(pluginXml[i]);
			for (int i = 0; i < pluginJars.length; i++)
				addFile(pluginJars[i]);
		}
		return true;
	}

	public static File[] getFilesInDirectory(File directory, String fileType,String excludeFilename) throws FileNotFoundException {
		Vector filesVector = new Vector();
		if (!directory.isDirectory())throw new FileNotFoundException("File directory must be a directory, which it isn't");
		File files[] = directory.listFiles();
		for (int i = 0; i < files.length; i++){
			if (getFileEnding(files[i].getName()).compareTo(fileType) == 0)
				if (excludeFilename != null) {					
					if (files[i].getName().compareTo(excludeFilename) != 0)
						filesVector.add(files[i]);
				} else {
					filesVector.add(files[i]);
				}
		}
		File matchingFiles[] = new File[filesVector.size()];
		for (int i = 0; i < filesVector.size(); i++)
			matchingFiles[i] = (File) filesVector.get(i);
		return matchingFiles;
	}

	private static File[] getFolderInDirectory(File directory)throws FileNotFoundException {
		Vector filesVector = new Vector();
		if (!directory.isDirectory())throw new FileNotFoundException("File directory must be a directory, which it isn't");
		File files[] = directory.listFiles();
		for (int i = 0; i < files.length; i++)
			if (files[i].isDirectory())
				filesVector.add(files[i]);
		File matchingFiles[] = new File[filesVector.size()];
		for (int i = 0; i < filesVector.size(); i++)
			matchingFiles[i] = (File) filesVector.get(i);
		return matchingFiles;
	}

	private static String getFileEnding(String filename) {
		if (filename == null)throw new IllegalArgumentException("Missing filename");
		String fileEnding = "";
		for (StringTokenizer st = new StringTokenizer(filename, "."); 
		st.hasMoreElements();)
			fileEnding = (String) st.nextElement();
		return fileEnding;
	}

	public static void addFile(File f) throws IOException {
		addURL(f.toURL());
	}

	public static void addURL(URL u) throws IOException {
		ClassLoader sysloader = Thread.currentThread().getContextClassLoader();
		if (sysloader == null)
			sysloader = ClassLoader.getSystemClassLoader();
		Class sysclass = java.net.URLClassLoader.class;
		try {
			Method method = sysclass.getDeclaredMethod("addURL", parameters);
			method.setAccessible(true);
			method.invoke(sysloader, new Object[] { u });
		} catch (Throwable t) {
			t.printStackTrace();
			throw new IOException("Error, could not add URL " + u+ " to system classloader");
		}
	}

	public void startServer(String args[]) throws ClassNotFoundException,InstantiationException, IllegalArgumentException,IllegalAccessException, InvocationTargetException {
		Class dynClass = Class.forName("org.dba.service.startService");
		Object app = dynClass.newInstance();
		Method methods[] = app.getClass().getMethods();
		for (int i = 0; i < methods.length; i++) {
			if (methods[i].getName().compareToIgnoreCase("startup") != 0)
				continue;
			Object params[] = new Object[2];
			params[0] = args;
			params[1] = ServerLoader.class.getClassLoader();
			methods[i].invoke(app, params);
			break;
		}
	}

	public void shutdownServer() throws ClassNotFoundException,InstantiationException, IllegalArgumentException,IllegalAccessException, InvocationTargetException {
		Class dynClass = Class.forName("org.dba.service.startService");
		Object app = dynClass.newInstance();
		Method methods[] = app.getClass().getMethods();
		for (int i = 0; i < methods.length; i++) {
			if (methods[i].getName().compareToIgnoreCase("shutdown") != 0)
				continue;
			Object params[] = (Object[]) null;
			methods[i].invoke(app, params);
			break;
		}
	}
}
